package com.gui.textFields;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.SwingUtilities;
import javax.swing.text.BadLocationException;
import javax.swing.text.Highlighter;
import javax.swing.text.JTextComponent;

/*
 *  Track the movement of the Caret by painting a background line at the
 *  current caret position.
 */
public class LinePainter implements Highlighter.HighlightPainter, KeyListener {

    private JTextComponent component;
    private Color color;
    private Rectangle lastView;
    private int lastPosition = 0;
    private Object highlighterTag;//used as key o remove highlighter;

    /*
     *  The line color will be calculated automatically by attempting
     *  to make the current selection lighter by a factor of 1.2.
     *
     *  @param component  text component that requires background line painting
     */
    public LinePainter(JTextComponent component) {
        this(component, null);
        setLighter(component.getSelectionColor());
    }

    /*
     *  Manually control the line color
     *
     *  @param component  text component that requires background line painting
     *  @param color      the color of the background line
     */
    public LinePainter(JTextComponent component, Color color) {
        init(component, color);
    }

    private void init(JTextComponent component, Color color) {
        this.component = component;
        setColor(color);
        component.addKeyListener(this);
        //  Turn highlighting on by adding a dummy highlight
        try {
            highlighterTag = component.getHighlighter().addHighlight(0, 0, this);
        } catch (BadLocationException ble) {
        }
    }

    public void deregisterPainter() {
        component.removeKeyListener(this);
        component.getHighlighter().removeHighlight(highlighterTag);
        resetHighlight();
    }

    /*
     *	You can reset the line color at any time
     *
     *  @param color  the color of the background line
     */
    public final void setColor(Color color) {
        this.color = color;
    }

    /*
     *  Calculate the line color by making the selection color lighter
     *
     *  @return the color of the background line
     */
    public final void setLighter(Color color) {
        int red = Math.min(255, (int) (color.getRed() * 1.2));
        int green = Math.min(255, (int) (color.getGreen() * 1.2));
        int blue = Math.min(255, (int) (color.getBlue() * 1.2));
        setColor(new Color(red, green, blue));
    }

    //  Paint the background highlight
    @Override
    public void paint(Graphics g, int p0, int p1, Shape bounds, JTextComponent c) {
        try {
            int offset = TextUtils.getStartOfLine(component, lastPosition);
            Rectangle r = c.modelToView(offset);
            g.setColor(color);
            g.fillRect(0, r.y, c.getWidth(), r.height);

            if (lastView == null) {
                lastView = r;
            }
        } catch (BadLocationException ble) {
            System.out.println(ble);
        }
    }

    public void setHighLightLine(int symbolPosition) {
        lastPosition = symbolPosition + 1;
        resetHighlight();
    }

    /*
     *   Caret position has changed, remove the highlight
     */
    private void resetHighlight() {
        //  Use invokeLater to make sure updates to the Document are completed,
        //  otherwise Undo processing causes the modelToView method to loop.

        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    int offset = TextUtils.getStartOfLine(component, lastPosition);
                    Rectangle currentView = component.modelToView(offset);
                    //  Remove the highlighting from the previously highlighted line
                    if (lastView != null) {
                        if (lastView.y != currentView.y) {
                            component.repaint(0, lastView.y, component.getWidth(), lastView.height);
                            lastView = currentView;
                        }
                    }
                } catch (BadLocationException ble) {
                }
            }
        });
    }

    @Override
    public void keyTyped(KeyEvent e) {
    }

    @Override
    public void keyPressed(KeyEvent e) {
        resetHighlight();
    }

    @Override
    public void keyReleased(KeyEvent e) {
    }
}
